﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
//操作word文档需要
using Word = Microsoft.Office.Interop.Word;
//判断文件是否打开状态
using System.Runtime.InteropServices;

namespace modifyDataTools
{
    public partial class Form1 : Form
    {
        string selectFolerPath = null;
        string extendsionString = null;
        List<string> allFiles = new List<string>();
        bool firstRun = true;
        //统计结果数组
        public struct resultsCount
        {
            public int modifyFileNameCount;
            public int modifyFileContentCount;
            public int modifyDirectoryNameCount;
        }
        resultsCount rlc = new resultsCount();
        
        ////////判断文件是否打开状态/////
        [DllImport("kernel32.dll")]
        private static extern IntPtr _lopen(string lpPathName, int iReadWrite);
        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr hObject);

        private const int OF_READWRITE = 2;

        private const int OF_SHARE_DENY_NONE = 0x40;
        private static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
        ////////////////////////////////       
        public Form1()
        {
            InitializeComponent();
            Init();
        }

        private void buttonSelectFolder_Click(object sender, EventArgs e)
        {
            int i = 0;
            allFiles.Clear();
            checkedListBoxAllFiles.Items.Clear();
           // rlc = new resultsCount();
            ////////////////选择文件夹//////////////
            FolderBrowserDialog folerBD = new FolderBrowserDialog();
            folerBD.Description = "选择相应文件夹";
            if (folerBD.ShowDialog() == DialogResult.OK)
            {
                selectFolerPath = folerBD.SelectedPath;
                textBoxFolderPath.Text = selectFolerPath;
            }
            firstRun = false;
            /////////////////获取所有文件并罗列在CheckedListBox中//////////
            updateCheckListBox(selectFolerPath);          
        }

        private void buttonSureReplace_Click(object sender, EventArgs e)
        {
            string resultString = null;           
            resultString=checkEmply();
            rlc = new resultsCount();
            string oldString=textBoxSeekString.Text.Trim();
            string newString=textBoxReplaceString.Text.Trim();
           
            if(resultString!=null)
            {
                MessageBox.Show(resultString);
                return;
            }       
            try
            {
                replaceDatas(oldString, newString);
                MessageBox.Show(string.Format("操作成功！\r\n更新文件夹{0}个\r\n更新文件名{1}个\r\n更新文件内容{2}个",
                    rlc.modifyDirectoryNameCount,rlc.modifyFileNameCount,rlc.modifyFileContentCount));
                updateCheckListBox(selectFolerPath);
            }
            catch (Exception em)
            {
                MessageBox.Show(em.Message);
                
            }       
            return;
            
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void checkBoxSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < checkedListBoxAllFiles.Items.Count; i++)
                checkedListBoxAllFiles.SetItemChecked(i, checkBoxSelectAll.Checked);
            updateLable();

        }

        private void checkedListBoxAllFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            updateLable();
        }


        #region 函数封装

        private void updateCheckListBox(string rootFoler)
        {
            int i = 0;
            allFiles.Clear();
            checkedListBoxAllFiles.Items.Clear();
            getDirectoriesAllFiles(rootFoler, allFiles, extendsionString);
            foreach (string file in allFiles)
            {
                checkedListBoxAllFiles.Items.Add(file.Replace(rootFoler, ""));
                checkedListBoxAllFiles.SetItemChecked(i++, true);
            }
            checkBoxSelectAll.Visible = true;
            checkBoxSelectAll.Checked = true;
            checkedListBoxAllFiles.Update();
            textBoxFolderPath.Text = selectFolerPath;
            updateLable();

        }
        /// <summary>
        /// 检查是否有未输入的
        /// </summary>
        /// <returns>null 表示全都输入了，其他则否</returns>
        private string checkEmply()
        {
            string returnString = null;
            returnString = textBoxReplaceString.Text == "" ? "请输入您要替换的字符串" : returnString;
            returnString = textBoxSeekString.Text == "" ? "请输入您要查找的字符串" : returnString;
            returnString = textBoxFolderPath.Text == "" ? "请选择您要操作的文件夹" : returnString;
            return returnString;
        }
        
        /// <summary>
        /// 根据文件扩展名嵌套获取所有文件
        /// </summary>
        /// <param name="fileOrDirectyPath">文件夹目录</param>
        /// <param name="allFiles">存放获取到的所有的文件路径</param>
        /// <param name="strFilterExtension">文件扩展名*表示全部|表示扩展名为空（格式：.txt|.doc）</param>
        /// <returns>true 成功，flase失败</returns>
        public bool getDirectoriesAllFiles(string fileOrDirectyPath, List<string> allFiles, string strFilterExtension)
        {
            string[] directories = null;
            string[] fileNames = null;
            string[] filterExtensions = null;      
            try
            {
                filterExtensions = strFilterExtension.ToLower().Split('|');
                #region 获取文件
                if (Directory.Exists(fileOrDirectyPath))
                {
                    directories = Directory.GetDirectories(fileOrDirectyPath);
                    foreach (string dir in directories)
                        getDirectoriesAllFiles(dir, allFiles, strFilterExtension);//递归

                    fileNames = Directory.GetFiles(fileOrDirectyPath);

                    foreach (string file in fileNames)
                        getDirectoriesAllFiles(file, allFiles, strFilterExtension);//递归

                }
                else
                {
                    if (filterExtensions.Contains(Path.GetExtension(fileOrDirectyPath).ToLower()) || filterExtensions.Contains("*"))//获取指定类型的文件
                        allFiles.Add(fileOrDirectyPath);

                }
                #endregion

            }
            catch (Exception)
            {
                MessageBox.Show("获取文件失败");
                return false;
            }
            return true;
        }
        /// <summary>
        /// 更新lable标签
        /// </summary>
        private void updateLable()
        {
            labelFilesNumber.Text = string.Format("{0}/{1}", checkedListBoxAllFiles.CheckedItems.Count, checkedListBoxAllFiles.Items.Count);
            labelFilesNumber.Update();
        }

        private void replaceDatas(string oldString, string newString)
        {           
            try
            {
                for (int i = 0; i < checkedListBoxAllFiles.CheckedItems.Count; i++)
                {
                    replaceDatasCore(selectFolerPath + checkedListBoxAllFiles.CheckedItems[i], oldString, newString);
                }
                //更新目录
                if(checkBoxFolder.Checked)
                    replaceDirfolderName(selectFolerPath, textBoxSeekString.Text.Trim(), textBoxReplaceString.Text.Trim());

            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            
        }
        private int replaceDatasCore(string filePath, string oldString, string newString)
        {
            string oldAllContent = null;
            string newAllContent = null;
            string newFileName = null;

            int returnValue = 0;
            //结果标记1：更新成功 0更新失败，-1：文件不存在
            int resultFlag = 0;
            
            
            string[] wordExtensions = new string[]{ ".doc",".wps",".rtf",".docx"};
            
            if (!File.Exists(filePath))
                return -1;
            try
            {
                //如果是word文档
                if (checkBoxFileContent.Checked && wordExtensions.Contains(Path.GetExtension(filePath)))
                {
                    resultFlag=returnValue=wordReplace(filePath, oldString, newString);
                    rlc.modifyFileContentCount+= returnValue;      
         
                }
                else
                {
                    oldAllContent = File.ReadAllText(filePath, ASCIIEncoding.Default);
                    //StreamReader sr = new StreamReader(filePath, ASCIIEncoding.GetEncoding("GBK"));
                    //oldAllContent = sr.ReadToEnd();
                    //sr.Close();   
                    ////////////修改文件内容/////////
                    if (checkBoxFileContent.Checked && Regex.Match(oldAllContent, oldString).Value != "")
                    {
                        newAllContent = Regex.Replace(oldAllContent, oldString, newString);
                        StreamWriter sw = new StreamWriter(filePath, false, ASCIIEncoding.Default);
                        sw.Write(newAllContent);
                        sw.Close();
                        rlc.modifyFileContentCount += 1;
                        resultFlag = 1;
                    }
                }
                          
                ////////////修改文件名///////////
                if(checkBoxFileName.Checked && Regex.Match(Path.GetFileName(filePath),oldString).Value!="" )
                {                   
                    newFileName = Regex.Replace(Path.GetFileName(filePath), oldString, newString);
                    File.Move(filePath, Path.Combine(Path.GetDirectoryName(filePath), newFileName));
                    rlc.modifyFileNameCount += 1;
                    resultFlag = 1;
                }                    
              
            }
            catch (Exception e)
            {
                //throw new Exception("读取文本或匹配替换文本/修改文件名出现异常！") ;
                throw new Exception(e.Message);  
            }
            return resultFlag;
        }

        /// <summary>
        /// 嵌套更新目录的名字
        /// </summary>
        /// <param name="rootFolder">根目录</param>
        /// <param name="oldString">需要更新的字符串</param>
        /// <param name="newString">更新的字符串</param>
        /// <param name="succeedCount">更新成功的目录数</param>
        private void replaceDirfolderName(string rootFolder,string oldString ,string newString)
        {
            string newFolderName = null;
            string newDirectory=null;
            string[] directories=null;
            if(Directory.Exists(rootFolder))
            {
                if (Regex.Match(Path.GetFileName(rootFolder), oldString).Value != "")
                {
                    
                    newFolderName = Regex.Replace(Path.GetFileName(rootFolder), oldString, newString);
                    newDirectory = Path.Combine(Path.GetDirectoryName(rootFolder), newFolderName);
                    Directory.Move(rootFolder, newDirectory);
                    rlc.modifyDirectoryNameCount++;
                    //更新根目录
                    selectFolerPath = (rootFolder == selectFolerPath ? newDirectory : selectFolerPath);
                    directories = Directory.GetDirectories(newDirectory);
                    
                }
                else
                {
                    directories = Directory.GetDirectories(rootFolder);
                }
                     
                foreach (string directory in directories)
                    replaceDirfolderName(directory, oldString, newString);                                
            }          
                       
        }

        #region word 更新内容
        /// <summary>
        /// 修改word文档中的内容
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="oldString">需要更新的字符串</param>
        /// <param name="newString">更新后的字符串</param>
        /// <returns>1更新成功，0没有找到字符</returns>
        private int wordReplace(string filePath, string oldString, string newString)
        {
            Word.Application app = new Word.Application();
            object nullObj = System.Reflection.Missing.Value;
            Word.Document doc = null;

            object file = filePath;
            if (1 == fileState(filePath))
            {
                throw new Exception("word处于打开状态，请先关闭它");
            }                  
            try
            {
               
                doc = app.Documents.Open(ref file, ref nullObj, ref nullObj,
                ref nullObj, ref nullObj, ref nullObj,
                ref nullObj, ref nullObj, ref nullObj,
                ref nullObj, ref nullObj, ref nullObj,
                ref nullObj, ref nullObj, ref nullObj,
                ref nullObj
                ) as Word.Document;

                app.Selection.Find.ClearFormatting();
                app.Selection.Find.Replacement.ClearFormatting();
                app.Selection.Find.Text = oldString;
                app.Selection.Find.Replacement.Text = newString;
                object objReplace = Word.WdReplace.wdReplaceAll;

                bool isSucceed = app.Selection.Find.Execute(ref nullObj, ref nullObj, ref nullObj,
                    ref nullObj, ref nullObj, ref nullObj,
                    ref nullObj, ref nullObj, ref nullObj,
                    ref nullObj, ref objReplace, ref nullObj,
                    ref nullObj, ref nullObj, ref nullObj);
     
                return isSucceed==true ? 1:0;
            }
            catch (Exception)
            {
                throw new Exception("操作word文档过程中出现异常！");
            }
            finally
            {
                doc.Save();
                doc.Close(ref nullObj, ref nullObj, ref nullObj);
                app.Quit(ref nullObj, ref nullObj, ref nullObj);

            }
            
        }
        /// <summary>
        /// 判断一个文件的状态
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>1打开状态，0不是打开状态，-1文件不存在</returns>
        private int fileState(string filePath)
        {

            if (!File.Exists(filePath))
            {
                return -1;
            }

            IntPtr handle = _lopen(filePath, OF_READWRITE | OF_SHARE_DENY_NONE);

            if (handle == HFILE_ERROR)
            {
                return 1;
            }

            CloseHandle(handle);

            return 0;
        }

        #endregion

        private void Init()
        {
            string initFilePath = Application.StartupPath + @"\init.txt";
            string[] initConfig = null;
            int defaultIndex=0;

            try
            {
                if (!File.Exists(initFilePath))
                {
                    MessageBox.Show("加载初始化配置文件失败！");
                    return;
                }
                initConfig = File.ReadAllLines(initFilePath, ASCIIEncoding.Default);

                string strCheckBoxFolder = initConfig[0];
                string strCheckBoxFileName = initConfig[1];
                string strCheckBoxFileContent = initConfig[2];

                /////////////配置combox/////
                checkBoxFolder.Checked = strCheckBoxFolder.Remove(strCheckBoxFolder.IndexOf('/')).Trim() == "1" ? true : false;
                checkBoxFileName.Checked = strCheckBoxFileName.Remove(strCheckBoxFileName.IndexOf('/')).Trim() == "1" ? true : false;
                checkBoxFileContent.Checked = strCheckBoxFileContent.Remove(strCheckBoxFileContent.IndexOf('/')).Trim() == "1" ? true : false;
                /////////////配置扩展名/////
                string strDefaultExtension = initConfig[initConfig.Length - 1];
                defaultIndex = int.Parse(strDefaultExtension.Remove(strDefaultExtension.IndexOf('/')).Trim())+2;
                comboBoxExtension.Text = initConfig[defaultIndex].Remove(initConfig[defaultIndex].IndexOf('/')).Trim();
                extendsionString = comboBoxExtension.Text;
                for (int i = 3; i < initConfig.Length - 1; i++)
                {
                    string extendsion = initConfig[i].Remove(initConfig[i].IndexOf('/')).Trim();
                    comboBoxExtension.Items.Add(extendsion);
                }
            }
            catch (Exception)
            {
                MessageBox.Show("配置文件加载异常!");
                this.Close();
            }
                                       

        }
        #endregion

        private void comboBoxExtension_SelectedValueChanged(object sender, EventArgs e)
        {
            if (!firstRun)
            {
                extendsionString = comboBoxExtension.Text.Trim();
                updateCheckListBox(selectFolerPath);
            }
        }

        private void comboBoxExtension_TextChanged(object sender, EventArgs e)
        {
            if(!firstRun)
            {
                extendsionString = comboBoxExtension.Text.Trim();
                updateCheckListBox(selectFolerPath);
            }
            

        }




    }
}
